package cn.ad.service;

import cn.ad.common.DataUtils;
import cn.ad.common.DateUtils;
import cn.ad.exception.NotMatchCreativeException;
import cn.ad.exception.StrategyGroupValidateException;
import cn.ad.exception.StrategyValidateException;
import cn.ad.handler.SqlSessionHandler;
import cn.ad.enumration.*;
import cn.ad.interceptor.PageParameter;
import cn.ad.model.*;
import cn.ad.entity.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.math.BigInteger;
import java.util.*;

/**
 * 策略服务实现
 * @author Administrator
 *
 */
@Service
public class StrategyService {

	private static Logger logger = LoggerFactory.getLogger(StrategyService.class);

	@Autowired
	private SqlSessionHandler sqlSessionHandler;

	@Autowired
	private CampaignService campaignService;

	@Autowired
	private StrategyGroupService strategyGroupService;

	@Autowired
	private CreativeGroupService creativeGroupService;

	@Autowired
	private CreativeService creativeService;

	@Autowired
	private GeoCityService geoCityService;

	@Autowired
	private InterestService interestService;

	/**
	 * 获取策略列表
	 * param searchMap: 查询map, pageInfo 分页信息
	 */
	@Transactional(readOnly = true)
	public ResultSetList<StrategyModel> findStrategies(Map<String,Object> searchMap, PageParameter pageInfo){
		//获取到策略列表
		List<StrategyModel> strategyList = sqlSessionHandler.selectList("strategyMapper.strategy:list:page", searchMap, pageInfo);
		//组成BO对象
		ResultSetList<StrategyModel> list = new ResultSetList<StrategyModel>(pageInfo.getTotalCount(), strategyList);

		return list;
	}

	/**
	 * 添加策略
	 * @throws
	 */
	@Transactional
	public void insertOrUpdate(Strategy strategyParam, Integer[] spaces, Integer[] creatives, Integer[] platforms,
                               TargetParam targetParam, boolean validate, List<CreativesGroups> creativesGroups,
                               boolean activate, Integer[] creativeGroupIds){
		TimeUpdateModel timeModel1 = new TimeUpdateModel(strategyParam.getStartTime(), strategyParam.getStartTime(),strategyParam.getCampaignId());
		TimeUpdateModel timeModel2 = new TimeUpdateModel(strategyParam.getEndTime(), strategyParam.getEndTime(),strategyParam.getCampaignId());
		timeModel1.setInclude(-1);
		timeModel2.setInclude(1);
		boolean isAdn = Platform.RESOURCETYPE_ADN.equals(strategyParam.getResType());
		int status = strategyParam.getStatus();
		//验证策略的时间、创意，组成更新订单时间的model
		validate(strategyParam,spaces,creatives,timeModel1,timeModel2,isAdn,platforms,creativesGroups,targetParam,creativeGroupIds);
		if(timeModel1.isUpdate()||timeModel2.isUpdate()){
			if(validate && 0 != strategyParam.getStatus()){
				//如果需要验证
				throw new StrategyValidateException(StrategyValidateException.ErrorCode.STRATEGY_CONFIRM);
			}
			if(validate && 0 == strategyParam.getStatus()){
				if(activate) {
					//如果需要验证
					throw new StrategyValidateException(StrategyValidateException.ErrorCode.STRATEGY_DATE);
				}else {
					//如果需要验证
					throw new StrategyValidateException(StrategyValidateException.ErrorCode.STRATEGY_CONFIRM);
				}
			}
		}
		if (timeModel2.isUpdate()) {
			sqlSessionHandler.update("campaignMapper.campaign:update:time", timeModel2);
		}
		if (timeModel1.isUpdate()) {
			sqlSessionHandler.update("campaignMapper.campaign:update:time", timeModel1);
		}
		strategyParam.setStatus(status);
		//通过ID验证为写入还是更新
		if(strategyParam.getId()==0){
			//最新添加
			//写入到策略表
			sqlSessionHandler.insert("strategyMapper.insert", strategyParam);
			logger.info("订单{}下添加了策略{}",strategyParam.getCampaignId(),strategyParam.getName());
		}else{
			if(null == strategyParam.getStatus()) {
				strategyParam.setStatus(this.readBase(strategyParam.getId()).getStatus());
			}
			sqlSessionHandler.update("strategyMapper.update", strategyParam);
			//资源=adn需要清除 策略广告位关系表、策略创意关系表
			if(isAdn) {

				sqlSessionHandler.update("strategySpaceMapMapper.deleteByStrategyId", strategyParam.getId());
				sqlSessionHandler.update("strategyCreativeGroupMapMapper.deleteByStrategyId",strategyParam.getId());
			}else {
				sqlSessionHandler.update("strategyPlatformMapMapper.deleteByStrategyId", strategyParam.getId());
			}
			//清除策略创意数据
			sqlSessionHandler.update("strategyCreativeMapMapper.deleteByStrategyId", strategyParam.getId());
			//清除时间定向数据
			sqlSessionHandler.update("strategyDayPartingMapper.deleteByStrategyId", strategyParam.getId());
			//清除地域定向数据
			sqlSessionHandler.update("strategyGeoMapMapper.deleteByStrategyId", strategyParam.getId());
			//清除设备定向数据
			sqlSessionHandler.update("strategyDeviceMapMapper.deleteByStrategyId", strategyParam.getId());
			//清除商业兴趣定向数据
			sqlSessionHandler.update("strategyInterestMapMapper.deleteByStrategyId", strategyParam.getId());
			//清除人群定向数据
			sqlSessionHandler.update("strategyCrowdMapMapper.deleteByStrategyId", strategyParam.getId());
			//清除关键字定向数据
			sqlSessionHandler.update("strategyKeywordMapMapper.deleteByStrategyId", strategyParam.getId());
			logger.info("编辑了订单{}下的策略{}",strategyParam.getCampaignId(),strategyParam.getName());
		}


		if(null != targetParam) {
			//写入到定向表
			insertTarget(targetParam,strategyParam.getId());
		}
		//私有资源需要储存 策略广告位关系表、策略创意关系表
		if(!DataUtils.isNull(spaces)) {
			//写入到策略广告位关系表，需批量写入
			insertSpaces(spaces,strategyParam.getId());
		}
		if(!DataUtils.isNull(creativeGroupIds)) {
			insertCreativeGroups(creativeGroupIds,strategyParam.getId());
		}else {
			//写入到策略创意关系表，需批量写入
			if(DataUtils.isNull(creatives) && !DataUtils.isNull(creativesGroups)) {
				List<Integer> creativeIdList = new ArrayList<>();
				for(CreativesGroups creativesGroup : creativesGroups) {
					List<Integer> creativeList = Arrays.asList(creativesGroup.getCreativeIds());
					if(!DataUtils.isNull(creativeList)) {
						creativeIdList.addAll(creativeList);
					}
				}
				creatives = creativeIdList.toArray(new Integer[creativeIdList.size()]);
			}
			if(!DataUtils.isNull(creatives)) {
				insertCreatives(creatives,strategyParam.getId());
			}
		}

	}
	/**
	 * 验证策略
	 * @param strategyParam
	 * @param timeModel1
	 * @param timeModel2
	 * @param isAdn
	 * @return
	 * @throws
	 */
	private void validate(Strategy strategyParam, Integer[] spaces, Integer[] creatives, TimeUpdateModel timeModel1,
                          TimeUpdateModel timeModel2, boolean isAdn, Integer[] platforms, List<CreativesGroups> creativesGroups,
                          TargetParam targetParam, Integer[] creativeGroupIds){

		// 订单下是否存在命名重复的策略
		if (isHasRepeat(strategyParam)) {
			throw new StrategyValidateException(StrategyValidateException.ErrorCode.STRATEGY_REPEAT);
		}
		if(null != strategyParam.getStatus() && strategyParam.getStatus() != 0) {
			checkTargetParams(targetParam);
			//策略与策略分组是否匹配
			StrategyGroup strategyGroup = null;
			if(strategyParam.getStrategyGroupId() > 0) {
				strategyGroup = strategyGroupService.findStrategyGroupById(strategyParam.getStrategyGroupId(),strategyParam.getCampaignId());
				if(null == strategyGroup) {
					throw new StrategyValidateException(StrategyValidateException.ErrorCode.STRATEGY_STRATEGYGROUP_NOTFOUND);
				}
				//策略资源类型是否和策略分组的资源类型一致
				if(!strategyGroup.getResourceType().equals(strategyParam.getResType())) {
					throw new StrategyValidateException(StrategyValidateException.ErrorCode.STRATEGY_RESOURCE_EDIT_WARNNING);
				}
			}
			if(Platform.RESOURCETYPE_ADX.equals(strategyParam.getResType())) {
				//平台数据是否有效
				if(!strategyGroupService.checkPlatfrom(platforms,strategyParam.getResType())) {
					throw new StrategyGroupValidateException(StrategyGroupValidateException.ErrorCode.STRATEGYGROUP_NOTFOUND_PLATFORM);
				}
			}
			//资源=adn时 需要判断广告位的广告形式与创意形式的匹配度
			if(isAdn) {
				// 3）每个广告位的广告形式 必须 匹配上 创意形式。否则在返回提示信息，文案待定。
				// 从广告位 匹配 创意的广告形式。 都能匹配上通过，如果原生形式的话，判断有没有对应模版的创意形式
				if(DataUtils.isNull(creatives) && DataUtils.isNull(creativeGroupIds)) {
					List<Integer> creativeIdList = new ArrayList<>();
					for(CreativesGroups creativesGroup : creativesGroups) {
						List<CreativeModel> creativeModels = creativeService.findCreateivesByCreateiveGroupId(strategyParam.getCampaignId(),creativesGroup.getId());
						if(DataUtils.isNull(creativeModels)) {
							throw new StrategyValidateException(StrategyValidateException.ErrorCode.STRATEGY_CREATIVEGROUP_NOTFOUND);
						}
						int count = 0;
						for(int cid : creativesGroup.getCreativeIds()) {
							for(CreativeModel creativeModel : creativeModels) {
								if(creativeModel.getId() == cid) {
									count++;
								}
							}
						}
						if(count != creativesGroup.getCreativeIds().length) {
							throw new StrategyValidateException(StrategyValidateException.ErrorCode.STRATEGY_CREATIVE_NOTFOUND);
						}
						List<Integer> creativeList = Arrays.asList(creativesGroup.getCreativeIds());
						if(!DataUtils.isNull(creativeList)) {
							creativeIdList.addAll(creativeList);
						}
					}
					creatives = creativeIdList.toArray(new Integer[creativeIdList.size()]);
				}
				// 策略对应的广告形式列表
				List<AdSpace> adpaceList = null;
				if(!DataUtils.isNull(spaces)) {
					adpaceList = sqlSessionHandler.selectList("adSpaceMapper.adspace:array:list", spaces);
					if(DataUtils.isNull(adpaceList)) {
						throw new StrategyValidateException(StrategyValidateException.ErrorCode.STRATEGY_NOT_SPACE);
					}
					List<AdSpace> creativeList = null;
					if(!DataUtils.isNull(spaces)) {
						creativeList = sqlSessionHandler.selectList("creativeMapper.creative:array:list", creatives);
					}
					if(DataUtils.isNull(creativeList)) {
						throw new StrategyValidateException(StrategyValidateException.ErrorCode.STRATEGY_CREATIVE_NOTFOUND);
					}
					for (AdSpace ad : adpaceList) {
						boolean flag = false;
						for (AdSpace c : creativeList) {
							if (ad.getFormatId() == c.getFormatId()) {
								if (ad.getTemplateId() == null || ad.getTemplateId().equals(c.getTemplateId()) || ad.getTemplateId() == c.getTemplateId()) {
									flag = true;
									break;
								}
							}
						}
						if (!flag) {
							// 如果在创意中找不到对应的广告形式的创意
							throw new NotMatchCreativeException(ad.getId());
						}
					}
				}
			}

			// 验证是否需要修改订单时间
			Date currDay = DateUtils.currDateDay();
			Strategy strategy = null;
			if (strategyParam.getId() != 0) {
				//验证编辑策略信息中的资源类型权限  注意：如果是编辑已有的策略信息的资源类型 是不允许的
				//查询策略表
				strategy =  this.readBase(strategyParam.getId());
				if(null == strategy) {
					throw new StrategyValidateException(StrategyValidateException.ErrorCode.STRATEGY_NOTFOUND);
				}
				if(!"".equals(strategy.getResType()) && !strategy.getResType().equals(strategyParam.getResType())) {
					throw new StrategyValidateException(StrategyValidateException.ErrorCode.STRATEGY_RESOURCE_EDIT_WARNNING);
				}
			}
			CampaignModel campaign = sqlSessionHandler.selectOne("campaignMapper.selectById", strategyParam.getCampaignId());
			//订单是否有效
			if(!(null != campaign ? true : false)) {
				throw new StrategyValidateException(StrategyGroupValidateException.ErrorCode.STRATEGYGROUP_NOTFOUND_COMPAGIN);
			}

			if (strategy != null) {
				// 修改策略时验证时间
				if (!strategy.getStartTime().equals(strategyParam.getStartTime())) {
					// 开始时间做出了修改
					if (isUpdateTime(strategy.getStartTime(), strategyParam.getStartTime(), currDay)) {
						if (strategyParam.getStartTime().before(campaign.getStartTime())) {
							timeModel1.setUpdate(true);
						}
					} else {
						throw new StrategyValidateException(StrategyValidateException.ErrorCode.STRATEGY_STARTDATE_WARNNING);
					}
				}
				if (!strategy.getEndTime().equals(strategyParam.getEndTime())) {
					// 结束时间做出了修改
					if (isUpdateTime(strategy.getEndTime(), strategyParam.getEndTime(), currDay)) {
						if (campaign.getEndTime().before(strategyParam.getEndTime())) {
							timeModel2.setUpdate(true);
						}
					} else {
						throw new StrategyValidateException(StrategyValidateException.ErrorCode.STRATEGY_ENDDATE_WARNNING);
					}
				}
				//是否是激活策略
				if(0 == strategy.getStatus() && 1 == strategyParam.getStatus()) {
					strategyParam.setStatus(0);
				}
			} else {
				// 新增策略时验证订单时间
				if (strategyParam.getStartTime().before(currDay)) {
					throw new StrategyValidateException(StrategyValidateException.ErrorCode.STRATEGY_STARTDATE_WARNNING);
				} else if (strategyParam.getEndTime().before(currDay)) {
					throw new StrategyValidateException(StrategyValidateException.ErrorCode.STRATEGY_ENDDATE_WARNNING);
				}
				if (strategyParam.getStartTime().before(campaign.getStartTime())) {
					timeModel1.setUpdate(true);
				}
				if (campaign.getEndTime().before(strategyParam.getEndTime())) {
					timeModel2.setUpdate(true);
				}
			}
		}

	}


	/**
	 * 判断时间输入是否正确
	 * @param data
	 * @param input
	 * @param currDay
	 * @return
	 */
	private boolean isUpdateTime(Date data, Date input, Date currDay){
		if(data.before(currDay)||input.before(currDay)){
			//抛出错误订单开始时间小于当前日期不能做出修改
			return false;
		}else{
			return true;
		}
	}

	/**
	 * 判断是否命名重复
	 * @param strategyParam
	 * @return
	 */
	private boolean isHasRepeat(Strategy strategyParam){
		Integer count = sqlSessionHandler.selectOne("strategyMapper.strategy:checkname", strategyParam);
		return count >0;
	}


	/**
	 * 写入策略创意关系表
	 * @param creatives 广告位id 数组
	 * @param id 策略id
	 * @return
	 */
	public int insertCreatives(Integer[] creatives, Integer id){
		List<StrategyCreativeMap> list = new ArrayList<>();
		for (Integer key : creatives) {
			if(null != key) {
				list.add(new StrategyCreativeMap(id,key));
			}
		}
		return sqlSessionHandler.insert("strategyCreativeMapMapper.insert:list", list);
	}
	/**
	 * 写入策略创意分组关系表
	 * @param creativeGroups 广告位id 数组
	 * @param id 策略id
	 * @return
	 */
	public int insertCreativeGroups(Integer[] creativeGroups, Integer id){
		List<StrategyCreativeGroupMap> list = new ArrayList<>();
		for (Integer key : creativeGroups) {
			if(null != key) {
				list.add(new StrategyCreativeGroupMap(id,key));
			}
		}
		return sqlSessionHandler.insert("strategyCreativeGroupMapMapper.insert:list", list);
	}

	/**
	 * 写入策略广告位关系表
	 * @param spaces
	 * @param id
	 * @return
	 */
	public int insertSpaces(Integer[] spaces, Integer id){
		List<StrategySpaceMap> list = new ArrayList<>();
		for (Integer key : spaces) {
			if(null != key) {
				list.add(new StrategySpaceMap(id,key));
			}
		}
		return sqlSessionHandler.insert("strategySpaceMapMapper.insert:list", list);
	}

	/**
	 * 写入策略平台关系表
	 * @param platformIds
	 * @param id 策略id
	 * @return
	 */
	private int insertPlatforms(Integer[] platformIds, Integer id){
		List<StrategyPlatformMap> list = new ArrayList<>();
		for (Integer key : platformIds) {
			if(null != key) {
				list.add(new StrategyPlatformMap(id,key));
			}
		}
		if(!DataUtils.isNull(list)) {
			return sqlSessionHandler.insert("strategyPlatformMapMapper.insert:list", list);
		}
		return 0;
	}


	/**
	 * 反转数组
	 *
	 * @since 1.1
	 * @param source
	 *            需要进行反转操作的数组
	 * @return 反转后的数组
	 */
	public static Integer[] reverse(Integer[] source) {
		int length = source.length;
		int temp = 0;
		for (int i = 0; i < length>>1; i++) {
			temp = source[i];
			source[i] = source[length - 1 - i];
			source[length - 1 - i] = temp;
		}
		return source;
	}

	/**
	 * 将数组转成10进制
	 * @return
	 */
	private static String radixToTen(Integer[] array){
		Integer[] arr = reverse(array);
		String s = StringUtils.arrayToDelimitedString(arr,"");
		BigInteger src = new BigInteger(s, 2);
		return src.toString();
	}

	/**
	 * 将十进制转成二进制
	 * @return
	 */
	private String radixToTwo(Integer value) {
		BigInteger src = new BigInteger(value.toString());// 转换为BigInteger类型
		return src.toString(2);
	}

	/**
	 * 添加定向信息
	 * @param tp
	 */
	public int insertTarget(TargetParam tp,Integer id){
		Integer[][] hours = tp.getHours();
		int i = 1;
		if(null != hours&&hours.length>0){
			//写入到时间定向表
			StrategyDayParting sdp = new StrategyDayParting();
			for(int j =0;j<hours.length;j++){
				if(j==0){
					sdp.setMonday(Integer.parseInt(radixToTen(hours[j])));
				}else if(j==1){
					sdp.setTuesday(Integer.parseInt(radixToTen(hours[j])));
				}else if(j==2){
					sdp.setWednesday(Integer.parseInt(radixToTen(hours[j])));
				}else if(j==3){
					sdp.setThursday(Integer.parseInt(radixToTen(hours[j])));
				}else if(j==4){
					sdp.setFriday(Integer.parseInt(radixToTen(hours[j])));
				}else if(j==5){
					sdp.setSaturday(Integer.parseInt(radixToTen(hours[j])));
				}else if(j==6){
					sdp.setSunday(Integer.parseInt(radixToTen(hours[j])));
				}
			}
			sdp.setStrategyId(id);
			i = sqlSessionHandler.insert("strategyDayPartingMapper.insert", sdp);
		}
		if(i==0) return i;
		Map<Integer,Integer> areas = tp.getArea();
		if(null !=areas&&areas.size()>0){
			List<StrategyGeoMap> list = new ArrayList<>();
			//写入到地域定向的表中
			for (Integer key : areas.keySet()) {
				list.add(new StrategyGeoMap(id,key,areas.get(key)));
			}
			i = sqlSessionHandler.insert("strategyGeoMapMapper.insert:list", list);
		}
		if(i==0) return i;
		/**====================设备定向信息储存===========================**/
		Integer[] connection = tp.getConnection();
		Integer[] os = tp.getOs();
		Integer[] telcom = tp.getTelcom();
		if(!DataUtils.isNull(connection) || !DataUtils.isNull(os) || !DataUtils.isNull(telcom)) {
			StrategyDeviceMap strategyDeviceMap = new StrategyDeviceMap();
			strategyDeviceMap.setStrategyId(id);
			strategyDeviceMap.setConnectType(this.integerToString(connection));
			strategyDeviceMap.setOperator(this.integerToString(telcom));
			strategyDeviceMap.setOs(this.integerToString(os));
			i = sqlSessionHandler.insert("strategyDeviceMapMapper.insert", strategyDeviceMap);
		}
		if(i==0) return i;
		/**=======================商业兴趣定向信息储存========================**/
		Integer[] interests = tp.getInterests();
		if(!DataUtils.isNull(interests)) {
			List<StrategyInserestMap> list = new ArrayList<>();
			for(int iid : interests) {
				list.add(new StrategyInserestMap(id,iid));
			}
			i = sqlSessionHandler.insert("strategyInterestMapMapper.insert:list", list);
		}
		if(i==0) return i;
		/**=====================人群定向信息储存========================**/
		Integer[] age = tp.getAge();
		String ages = tp.getAges();
		Integer[] income = tp.getIncome();
		Integer[] educations = tp.getEducation();
		Integer[] genders = tp.getGender();
		Integer[] marriage= tp.getMarriage();
		StrategyCrowdMap strategyCrowdMap = new StrategyCrowdMap();
		strategyCrowdMap.setStrategyId(id);
		strategyCrowdMap.setGender(DataUtils.isNull(genders) ? "" : DataUtils.sum(genders).toString());
		strategyCrowdMap.setAge(DataUtils.isNull(ages) ? DataUtils.isNull(age) ? "" : DataUtils.sum(age).toString(): ages);
		strategyCrowdMap.setEducation(DataUtils.isNull(educations) ? "" : DataUtils.sum(educations).toString());
		strategyCrowdMap.setIncome(DataUtils.isNull(income) ? "" : DataUtils.sum(income).toString());
		strategyCrowdMap.setMarriage(DataUtils.isNull(marriage) ? "" : DataUtils.sum(marriage).toString());
		if(null !=strategyCrowdMap && (!DataUtils.isNull(strategyCrowdMap.getGender()) || !DataUtils.isNull(strategyCrowdMap.getAge())
				|| !DataUtils.isNull(strategyCrowdMap.getEducation()) || !DataUtils.isNull(strategyCrowdMap.getIncome()) || !DataUtils.isNull(strategyCrowdMap.getMarriage()) ))
			i = sqlSessionHandler.insert("strategyCrowdMapMapper.insert", strategyCrowdMap);
		if(i==0) return i;
		/**=====================关键字定向信息储存========================**/
		String keyword = tp.getKeyword();
		if(!DataUtils.isNull(keyword)) {
			StrategykeywordMap strategykeywordMap = new StrategykeywordMap();
			strategykeywordMap.setStrategyId(id);
			strategykeywordMap.setKeyword(keyword);
			return sqlSessionHandler.insert("strategyKeywordMapMapper.insert", strategykeywordMap);
		}
		return 0;
	}

	/**
	 * 定向信息是否存在
	 * @param tp
	 */
	private void checkTargetParams(TargetParam tp) {
		if(null != tp) {
			/**====================地域定向信息储存===========================**/
			Map<Integer,Integer> areas = tp.getArea();
			if(!DataUtils.isNull(areas)) {
				List<Tree> list = geoCityService.getGeoList();
				int count = 0;
				for(Tree t : list) {
					if(areas.containsKey(Integer.parseInt(t.getId().substring(0,t.getId().length()-2)))) {
						count++;
					}
				}
				if(count < areas.size()) {
					throw new StrategyValidateException(StrategyValidateException.ErrorCode.STRATEGY_AREAS);
				}
			}
			/**====================设备定向信息储存===========================**/
			Integer[] connection = tp.getConnection();
			Integer[] os = tp.getOs();
			Integer[] telcom = tp.getTelcom();
			Map<Integer,String> paramsMap = null;
			if(!DataUtils.isNull(connection)) {
				paramsMap = Connection.getMapping();
				for(int i : connection) {
					if(!paramsMap.containsKey(i)) {
						throw new StrategyValidateException(StrategyValidateException.ErrorCode.STRATEGY_CONNECTION);
					}
				}
			}
			if(!DataUtils.isNull(os)) {
				paramsMap = OsType.getMapping();
				for(int i : os) {
					if(!paramsMap.containsKey(i)) {
						throw new StrategyValidateException(StrategyValidateException.ErrorCode.STRATEGY_OSTYPE);
					}
				}
			}
			if(!DataUtils.isNull(telcom)) {
				paramsMap = Operator.getMapping();
				for(int i : telcom) {
					if(!paramsMap.containsKey(i)) {
						throw new StrategyValidateException(StrategyValidateException.ErrorCode.STRATEGY_OPERATOR);
					}
				}
			}
			/**=======================商业兴趣定向信息储存========================**/
			Integer[] interests = tp.getInterests();
			if(!DataUtils.isNull(interests)) {
				List<Interest> list = interestService.getInterestMap();
				int count = 0;
				for(int i : interests) {
					for(Interest interest:list) {
						if(interest.getId() == i) {
							count ++;
						}
					}
				}
				if(count != interests.length) {
					throw new StrategyValidateException(StrategyValidateException.ErrorCode.STRATEGY_INTERESTS);
				}
			}
			/**=====================人群定向信息储存========================**/
			Integer[] age = tp.getAge();
			Integer[] income = tp.getIncome();
			Integer[] educations = tp.getEducation();
			Integer[] genders = tp.getGender();
			Integer[] marriage= tp.getMarriage();
			Map<String,Integer> paramsMap1 = null;
			if(!DataUtils.isNull(age)) {
				paramsMap1 = Age.getMapping();
				for(int i : age) {
					if(!paramsMap1.containsValue(i)) {
						throw new StrategyValidateException(StrategyValidateException.ErrorCode.STRATEGY_AGE);
					}
				}
			}
			if(!DataUtils.isNull(income)) {
				paramsMap1 = Income.getMapping();
				for(int i : income) {
					if(!paramsMap1.containsValue(i)) {
						throw new StrategyValidateException(StrategyValidateException.ErrorCode.STRATEGY_INCOME);
					}
				}
			}
			if(!DataUtils.isNull(educations)) {
				paramsMap1 = Education.getMapping();
				for(int i : educations) {
					if(!paramsMap1.containsValue(i)) {
						throw new StrategyValidateException(StrategyValidateException.ErrorCode.STRATEGY_EDUCATIONS);
					}
				}
			}
			if(!DataUtils.isNull(genders)) {
				paramsMap1 = Gender.getMapping();
				for(int i : genders) {
					if(!paramsMap1.containsValue(i)) {
						throw new StrategyValidateException(StrategyValidateException.ErrorCode.STRATEGY_GENDERS);
					}
				}
			}
			if(!DataUtils.isNull(marriage)) {
				paramsMap1 = Marriage.getMapping();
				for(int i : marriage) {
					if(!paramsMap1.containsValue(i)) {
						throw new StrategyValidateException(StrategyValidateException.ErrorCode.STRATEGY_MARRIAGE);
					}
				}
			}
		}

	}
	/**
	 * 数组转字符串
	 * @param i
	 * @return
	 */
	private String integerToString(Integer[] i) {
		String str = "";
		if(!DataUtils.isNull(i)) {
			for(int k : i) {
				str+=k+",";
			}
			return str.substring(0,str.length()-1);
		}
		return str;
	}

	/**
	 * 策略状态修改
	 */
	@Transactional
	public void updateStatus(Integer cid, Integer id, Integer status) {

		this.checkCampaign(cid);
		Strategy strategy = this.checkStrategy(id, cid);
		if(strategy.getStatus() == 0 && status == 1) {
			throw new StrategyValidateException(StrategyValidateException.ErrorCode.STRATEGY_STATUS);
		}
		this.checkStrategrStatus(status);
		HashMap<String, Integer> map = new HashMap<String,Integer>(2);
		map.put("id", id);
		map.put("campaignId", cid);
		map.put("status", status);
		sqlSessionHandler.update("strategyMapper.updateStatus", map);
		logger.info("修改了策略{}的状态,当前状态值为{}",id,status);
	}
	/**
	 * 策略状态修改
	 */
	@Transactional
	public void updateStatusForStaregy(Integer cid, Integer id, Integer status) {
		this.checkStrategrStatus(status);
		HashMap<String, Integer> map = new HashMap<String,Integer>(2);
		map.put("id", id);
		map.put("campaignId", cid);
		map.put("status", status);
		sqlSessionHandler.update("strategyMapper.updateStatus", map);
		logger.info("修改了策略{}的状态,当前状态值为{}",id,status);
	}

	/**
	 * 验证订单是否有效
	 * @param campaignId
	 */
	private void checkCampaign(int campaignId){
		//订单是否有效
		if(!(null != campaignService.getCampaignById(campaignId) ? true : false)) {
			throw new StrategyValidateException(StrategyGroupValidateException.ErrorCode.STRATEGYGROUP_NOTFOUND_COMPAGIN);
		}
	}
	/**
	 * 验证策略是否存在
	 * @param id
	 */
	private Strategy checkStrategy(int id,int campaignId){
		//策略分组是否存在
		Strategy strategy = this.read(id);
		if(null == strategy) {
			throw new StrategyValidateException(StrategyValidateException.ErrorCode.STRATEGY_NOTFOUND);
		}
		if(strategy.getCampaignId() != campaignId) {
			throw new StrategyValidateException(StrategyValidateException.ErrorCode.STRATEGY_NOTFOUND);
		}
		return strategy;
	}
	/**
	 * 验证策略是否存在状态临界值
	 * @param status
	 */
	private void checkStrategrStatus(Integer status){
		if(StrategyStatus.ADSTATUS_DELETED.getValue() != status &&
				StrategyStatus.ADSTATUS_FINISH.getValue() != status &&
				StrategyStatus.ADSTATUS_NORMAL.getValue() != status &&
				StrategyStatus.ADSTATUS_RESET.getValue() != status &&
				StrategyStatus.ADSTATUS_RUNNING.getValue() != status &&
				StrategyStatus.ADSTATUS_SUSPEND.getValue() != status) {
			throw new StrategyValidateException(StrategyValidateException.ErrorCode.STRATEGY_NOTFOUND_STATUS);
		}
	}

	/**
	 * 查询单个策略信息
	 */
	@Transactional
	public Strategy read(Integer id) {
		return sqlSessionHandler.selectOne("strategyMapper.selectById", id);
	}
	/**
	 * 查询基本单个策略信息
	 */
	@Transactional
	public Strategy readBase(Integer id) {
		return sqlSessionHandler.selectOne("strategyMapper.select:by:Id", id);
	}

	/**
	 * 查询时间定向数据
	 */
	@Transactional
	public Integer[][] readTargetTime(Integer id) {
		StrategyDayParting strategyDayParting = sqlSessionHandler.selectOne("strategyDayPartingMapper.selectByStrategyId", id);
		if(strategyDayParting!=null){
			String[] array = new String[7];
			array[0] = new StringBuilder(addZeroForNum(24, radixToTwo(strategyDayParting.getMonday()))).reverse().toString();
			array[1] = new StringBuilder(addZeroForNum(24, radixToTwo(strategyDayParting.getTuesday()))).reverse().toString();
			array[2] = new StringBuilder(addZeroForNum(24, radixToTwo(strategyDayParting.getWednesday()))).reverse().toString();
			array[3] = new StringBuilder(addZeroForNum(24, radixToTwo(strategyDayParting.getThursday()))).reverse().toString();
			array[4] = new StringBuilder(addZeroForNum(24, radixToTwo(strategyDayParting.getFriday()))).reverse().toString();
			array[5] = new StringBuilder(addZeroForNum(24, radixToTwo(strategyDayParting.getSaturday()))).reverse().toString();
			array[6] = new StringBuilder(addZeroForNum(24, radixToTwo(strategyDayParting.getSunday()))).reverse().toString();

			return convertToIntegerArray(array);
		}
		return null;
	}


	/**
	 * 获取策略地域定向数据
	 */
	@Transactional
	public List<Tree> readTargetArea(Integer id) {
		List<Tree> list = sqlSessionHandler.selectList("strategyGeoMapMapper.selectByStrategyId", id);
		return list;
	}
	/**
	 * 将时间定向的字符串转换成Integer[][]
	 * @param array
	 * @return
	 */
	private Integer[][] convertToIntegerArray(String[] array){
		Integer[][] result = new Integer[array.length][];
		int j=0;
		for(String str:array){
			Integer ret[] = new Integer[str.length()];
			for(int i = 0;i<str.length();i++){
				ret[i] =  Integer.parseInt(String.valueOf(str.charAt(i)));
			}
			result[j]=ret;
			j++;
		}
		return result;
	}

	/**
	 * 补0到24位
	 * @param strLength
	 * @param str
	 * @return
	 */
	private String addZeroForNum(int strLength, String str) {
		int strLen = str.length();
		StringBuffer sb = null;
		while (strLen < strLength) {
			sb = new StringBuffer();
			sb.append("0").append(str);// 左(前)补0
			str = sb.toString();
			strLen = str.length();
		}
		return str;
	}

	/**
	 * 快捷更新竞价
	 */
	@Transactional
	public void updateUnitPrice(Integer cid, int id, double unitPrice) {
		Strategy strategy = new Strategy();
		strategy.setId(id);
		strategy.setCampaignId(cid);
		strategy.setUnitPrice(unitPrice);
		sqlSessionHandler.update("strategyMapper.update:strategy:unit:price", strategy);
		logger.info("更新了策略{}的出价为{}",id,unitPrice);
	}


	@Transactional
	public List<Strategy> selectStrategyList(Map<String, Object> searchMap){
		return sqlSessionHandler.selectList("strategyMapper.select:strategy:list", searchMap);
	}

	public List<Strategy> selectStrategyListFromStrategyGroup(Map<String, Object> searchMap) {
		return sqlSessionHandler.selectList("strategyMapper.select:strategyGroup:list", searchMap);
	}


	@Transactional
	public List<AdSpace> getAdSpaceListForCampaign(Integer campaignId) {
		Map<String, Object> params = new HashMap<String, Object>();
		params.put("campaignId", campaignId);
		return sqlSessionHandler.selectList("strategyMapper.select:adspace:list", params);
	}

	/**
	 * 获取某策略下的人群定向信息
	 * @param strategyId
	 * @return
	 */
	@Transactional
	public StrategyCrowdMap getStrategyCrowdMapByStrategyId(Integer strategyId) {
		return sqlSessionHandler.selectOne("strategyCrowdMapMapper.selectByStrategyId", strategyId);
	}

	/**
	 * 获取某策略下的设备定向信息
	 * @param strategyId
	 * @return
	 */
	@Transactional
	public StrategyDeviceMap getStrategyDeviceMapByStrategyId(Integer strategyId) {
		return sqlSessionHandler.selectOne("strategyDeviceMapMapper.selectByStrategyId", strategyId);
	}

	/**
	 * 获取某策略下的商业兴趣定向信息
	 * @param strategyId
	 * @return
	 */
	@Transactional
	public List<Interest> getStrategyInterestMapByStrategyId(Integer strategyId) {
		return sqlSessionHandler.selectList("InterestMapper.selectByStrategyId", strategyId);
	}

	/**
	 * 获取某策略下的关键字定向信息
	 * @param strategyId
	 * @return
	 */
	@Transactional
	public StrategykeywordMap getStrategykeywordMapByStrategyId(Integer strategyId) {
		return sqlSessionHandler.selectOne("strategyKeywordMapMapper.selectByStrategyId", strategyId);
	}

	public CampaignTag getCampaignTag(Integer campaignId) {
		return sqlSessionHandler.selectOne("campaignTagMapper.selectByCampaignId",campaignId);
	}

	public void updateStrategyTargetData(TargetParam targetParam, int strategyId) {
		this.deleteStrategyTargetData(targetParam,strategyId);
		//写入到定向表
		insertTarget(targetParam,strategyId);
	}

	public void delStrategyTargetData(TargetParam targetParam, int strategyId) {
		this.deleteStrategyTargetData(targetParam,strategyId);
	}

	private void deleteStrategyTargetData(TargetParam targetParam, int strategyId) {
		if(null == this.readBase(strategyId)) {
			throw new StrategyValidateException(StrategyValidateException.ErrorCode.STRATEGY_NOTFOUND);
		}
		if((null != targetParam.getHours()&&targetParam.getHours().length>0) ||
				(!DataUtils.isNull(targetParam.getDelStr()) && targetParam.getDelStr().indexOf("1") != -1)){
			//清除时间定向数据
			sqlSessionHandler.update("strategyDayPartingMapper.deleteByStrategyId", strategyId);
		}
		Map<Integer,Integer> areas = targetParam.getArea();
		if((null !=areas&&areas.size()>0) ||
				(!DataUtils.isNull(targetParam.getDelStr()) && targetParam.getDelStr().indexOf("2") != -1)){
			//清除地域定向数据
			sqlSessionHandler.update("strategyGeoMapMapper.deleteByStrategyId", strategyId);
		}
		/**====================设备定向信息储存===========================**/
		Integer[] connection = targetParam.getConnection();
		Integer[] os = targetParam.getOs();
		Integer[] telcom = targetParam.getTelcom();
		if(!DataUtils.isNull(connection) || !DataUtils.isNull(os) || !DataUtils.isNull(telcom)  ||
				(!DataUtils.isNull(targetParam.getDelStr()) && targetParam.getDelStr().indexOf("5") != -1)) {
			//清除设备定向数据
			sqlSessionHandler.update("strategyDeviceMapMapper.deleteByStrategyId", strategyId);
		}
		/**=======================商业兴趣定向信息储存========================**/
		Integer[] interests = targetParam.getInterests();
		if(!DataUtils.isNull(interests) ||
				(!DataUtils.isNull(targetParam.getDelStr()) && targetParam.getDelStr().indexOf("4") != -1)) {
			//清除商业兴趣定向数据
			sqlSessionHandler.update("strategyInterestMapMapper.deleteByStrategyId", strategyId);
		}
		/**=====================人群定向信息储存========================**/
		Integer[] age = targetParam.getAge();
		Integer[] income = targetParam.getIncome();
		Integer[] educations = targetParam.getEducation();
		Integer[] genders = targetParam.getGender();
		Integer[] marriage= targetParam.getMarriage();
		if(!DataUtils.isNull(age) || !DataUtils.isNull(income) ||
				!DataUtils.isNull(educations) || !DataUtils.isNull(genders) ||
				!DataUtils.isNull(marriage) ||
				(!DataUtils.isNull(targetParam.getDelStr()) && targetParam.getDelStr().indexOf("3") != -1)) {
			//清除人群定向数据
			sqlSessionHandler.update("strategyCrowdMapMapper.deleteByStrategyId", strategyId);
		}
		/**=====================关键字定向信息储存========================**/
		String keyword = targetParam.getKeyword();
		if(!DataUtils.isNull(keyword) ||
				(!DataUtils.isNull(targetParam.getDelStr()) && targetParam.getDelStr().indexOf("6") != -1)) {
			//清除关键字定向数据
			sqlSessionHandler.update("strategyKeywordMapMapper.deleteByStrategyId", strategyId);
		}
	}
}
